package thesis.filesharing.dao.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import thesis.filesharing.common.exception.system.AppSystemException;
import thesis.filesharing.dao.SubjectDAO;
import thesis.filesharing.dao.util.EMF;
import thesis.filesharing.model.Subject;

import com.google.appengine.api.datastore.Key;

@Repository
public class SubjectDAOImpl implements SubjectDAO {

	@SuppressWarnings("unchecked")
	@Override
	public List<Subject> listSubjects(int page, int pageSize) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			String jpaql = "SELECT s FROM Subject s ORDER BY s.subjectId";
			Query query = em.createQuery(jpaql);
			query.setFirstResult((page - 1) * pageSize);
			query.setMaxResults(pageSize);
			return (List<Subject>) query.getResultList();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public int countSubjects() {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			String jpaql = "SELECT s FROM Subject s";
			Query query = em.createQuery(jpaql);
			return query.getResultList().size();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public Subject findSubjectById(String subjectId) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			String jpaql = "SELECT s FROM Subject s WHERE s.subjectId = :subjectId";
			Query query = em.createQuery(jpaql);
			query.setParameter("subjectId", subjectId);
			List<Subject> subjects = (List<Subject>) query.getResultList();
			if (subjects != null && !subjects.isEmpty()) {
				Subject s = subjects.get(0);
				s.getClasses().size();
				return s;
			}
			return null;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		} finally {
			em.close();
		}
	}

	@Override
	public Subject saveSubject(Subject subject) {
		EntityManager em = null;
		EntityTransaction transaction = null;
		try {
			em = EMF.get().createEntityManager();
			transaction = em.getTransaction();
			transaction.begin();
			
			em.persist(subject);
			em.flush();
			
			transaction.commit();
			return subject;
		} catch (Exception ex) {
			if (transaction != null && transaction.isActive()) {
				transaction.rollback();
			}
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public void deleteSubject(Key subjectKey) {
		EntityManager em = null;
		EntityTransaction transaction = null;
		
		try {
			em = EMF.get().createEntityManager();
			transaction = em.getTransaction();
			transaction.begin();
			
			Subject subject = em.find(Subject.class, subjectKey);
			if (subject != null) {
				em.remove(subject);
			}
			
			transaction.commit();
		} catch (Exception ex) {
			if (transaction != null && transaction.isActive()) {
				transaction.rollback();
			}
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public Subject updateSubject(Subject subject) {
		EntityManager em = null;
		EntityTransaction transaction = null;
		
		try {
			em = EMF.get().createEntityManager();
			transaction = em.getTransaction();
			transaction.begin();
			
			Subject s = em.find(Subject.class, subject.getSubjectKey());
			if (s != null) {
				s.setSubjectId(subject.getSubjectId());
				s.setSubjectName(subject.getSubjectName());
				if (subject.getClasses() != null && !subject.getClasses().isEmpty()) {
					s.getClasses().addAll(subject.getClasses());
				}
				em.merge(s);
				em.flush();
			}
			
			transaction.commit();
			return s;
		} catch (Exception ex) {
			if (transaction != null && transaction.isActive()) {
				transaction.rollback();
			}
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public Subject findSubjectByKey(Key subjectKey) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			Subject s = em.find(Subject.class, subjectKey);
			// For activating lazy load
			if (s != null) {
				s.getClasses().size();
			}
			return s;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		} finally {
			em.close();
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean checkUpdatedSubjectExisted(Key subjectKey, String subjectId) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			String jpaql = "SELECT s FROM Subject s WHERE s.subjectId = :subjectId AND s.subjectKey <> :subjectKey";
			Query query = em.createQuery(jpaql);
			query.setParameter("subjectKey", subjectKey);
			query.setParameter("subjectId", subjectId);
			List<Subject> subjects = (List<Subject>) query.getResultList();
			return subjects != null && !subjects.isEmpty();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		} finally {
			em.close();
		}
	}
}
